#include "RSA.h"
#include <cmath>
#include <iostream>
#include <vector>

inline unsigned __int64 MulMod(unsigned __int64 a, unsigned __int64 b, unsigned __int64 n)
{
    return a * b % n;
}
/*
模幂运算，返回值 x=base^pow mod n
*/
unsigned __int64 PowMod(unsigned __int64 base, unsigned __int64 pow, unsigned __int64& n)
{
    unsigned __int64 a = base, b = pow, c = 1;
    while (b) {
        while (!(b & 1)) {
            b >>= 1; //a=a * a % n; //
            a = MulMod(a, a, n);
        }
        b--; //c=a * c % n; //
        c = MulMod(a, c, n);
    }
    return c;
}

// 这个存在溢出问题  不知该怎么解决
static uint64_t montgomery(uint64_t m, uint64_t e, uint64_t n)
{
    uint64_t k = 1;
    m %= n;
    while (e > 0) {
        if ((e & 1) != 0)
            k = (k * m) % n;
        m = (m * m) % n;  // 注意溢出
        e >>= 1;
    }
    return k;
}

int main()
{
    RSA rsa;
    rsa.genKey();
    vector<uint64_t> raw = rsa.encrypt("so difficult@qq.com");
    for (auto&& i : raw) {
        println("encrypted:", i);
    }
    string msg = rsa.decrypt(raw);
    println("decrypted:", msg);

    int bitsr[3] = { 0 };
    int bits = 64;
    int primes = 2;
    int quo = bits / primes;
    println("quo:", quo);
    int rmd = bits % primes;
    println("rmd:", rmd);

    for (int i = 0; i < primes; i++)
        bitsr[i] = (i < rmd) ? quo + 1 : quo;

    char sep[3] = { '\0', ' ', '\0' };
    for (auto&& i : bitsr) {
        std::cout << sep << i;
        sep[0] = ',';
    }
    println();

    uint64_t e = 65537, n = 2531371187, d = 1789891793;
    uint64_t m = 395802;
    // println(rsa.gcd(d, 2723326056));
    println("montgomery:", montgomery(m, e, n));
    uint64_t enc = montgomery(m, e, n);
    println("montgomery:", montgomery(enc, d, n)); // 为什么就是不对，心态崩了，原来是溢出了

    println("powmode:", PowMod(m, e, n));
    unsigned long long enc4 = PowMod(m, e, n);
    println("powmode:", PowMod(enc4, d, n));  // 为什么就是不对，心态崩了

    return 0;
}
